﻿using System.Linq;
using System.Web.Mvc;
using Moq;
using NUnit.Framework;
using Safal.IncidentTracker.Domain.Abstract;
using Safal.IncidentTracker.Domain.Entities;
using Safal.IncidentTracker.WebUI.Controllers;

namespace Safal.IncidentTracker.Tests
{
    [TestFixture]
    public class EditIncidents
    {
        private Mock<IIncidentsRepository> _mockIncidents;

        [SetUp]
        public void SetUp()
        {
            _mockIncidents = new Mock<IIncidentsRepository>();
        }
        [Test]
        public void Can_Edit_A_Incident()
        {
            // Arrange
            Mock<IIncidentsRepository> repository = UnitTestHelpers.MockIncidentsRepository(
                   new Incident { Id = 9, Title = "Fix Machine #1", },
                   new Incident { Id = 51, Title = "Fix Machine #2", },
                   new Incident { Id = 3, Title = "Fix Machine #3", }
               );

            var controller = new IncidentsController(repository.Object);
            // Act
            var result = controller.Edit(51);
            // Assert
            result.ShouldBeView(string.Empty);
            var viewData = ((ViewResult) result).ViewData;
            Assert.That(((Incident)viewData.Model).Id, Is.EqualTo(51));

        }

        [Test]
        public void Can_Save_Edited_Incident()
        {
            // Arrange
            var incident = new Incident { Id = 1, Title = "Accident #1" };
            var updatedIncident = new Incident { Id = 1, Title = "Accident #1 Updated" };

            _mockIncidents.Setup(r => r.Incidents).Returns(new[] { incident }.AsQueryable());

            var controller = new IncidentsController(_mockIncidents.Object)
                .WithIncomingValues(new FormCollection
                {
                    {"Id", "1"},
                    {"Title", "Accident #1 Updated"},
                    {"Casualty", "David"},
                    {"Description", "Desc"},
                    {"InjuryType", "Fracture"},
                    {"InjuryLocation", "Arm"}
                });

            // Act  
            var result = controller.Edit(updatedIncident);

            // Assert
            _mockIncidents.Verify(r => r.Incidents, Times.Once());
            _mockIncidents.Verify(r => r.SaveIncident(incident), Times.Once());
            result.ShouldBeRedirectionTo(new { action = "List", page = 1 });

        }
        [Test]
        public void Cannot_Save_Invalid_Incident()
        {
            // Arrange
            var incident = new Incident { Id = 15, Title = "Fix Machine #1" };
            _mockIncidents.Setup(r => r.Incidents).Returns(new[] { incident }.AsQueryable());

            var controller = new IncidentsController(_mockIncidents.Object).WithIncomingValues(new FormCollection
                {
                    {"JobID", "15"},
                    {"Title", "Fix Machine #1 Updated"}
                });

            controller.ViewData.ModelState.AddModelError("key", "message");

            // Act
            var result = controller.Edit(incident);

            // Assert
            Assert.That(((ViewResult)result).ViewName, Is.EqualTo(string.Empty));
        }

        [Test]
        public void Can_Create_New_Incident()
        {
            // Arrange
            var controller = new IncidentsController(null);

            // Act
            var result = controller.Create();

            // Assert
            result.ShouldBeView("Edit");
        }

        [Test]
        public void Can_Delete_Existing_Incident()
        {
            // Arrange
            Incident incidentToDelete = new Incident { Id = 9, Title = "Fix Machine #1" };
            Mock<IIncidentsRepository> repository = UnitTestHelpers.MockIncidentsRepository(
                  new Incident { Id = 51, Title = "Fix Machine #2", },
                  new Incident { Id = 3, Title = "Fix Machine #3", },
                  incidentToDelete
              );
            
            var controller = new IncidentsController(repository.Object)
                .WithIncomingValues(
                    new FormCollection {
                                           {"JobID","9"}
                                       }
                );

            // Act
            var result = controller.Delete(9);

            // Assert
            repository.Verify(m => m.DeleteIncident(incidentToDelete), Times.Once());
            result.ShouldBeRedirectionTo(new { action = "List", page = 1 });
        }
        [Test]
        public void Cannot_Edit_NonExistant_Incident()
        {
            // Arrange
            Mock<IIncidentsRepository> repository = UnitTestHelpers.MockIncidentsRepository(
                  new Incident { Id = 1 }
            );

            var controller = new IncidentsController(repository.Object);

            // Act
            var result = controller.Edit(2);

            // Assert
            Assert.That(controller.TempData["ErrorMessage"], Is.EqualTo("Cannot Find incident"));
            result.ShouldBeRedirectionTo(new { action = "List", page = 1 });
        }

        [Test]
        public void Cannot_Delete_NonExistant_Incident()
        {
            // Arrange
            Mock<IIncidentsRepository> repository = UnitTestHelpers.MockIncidentsRepository(
                  new Incident { Id = 1 }
            );

            var controller = new IncidentsController(repository.Object);

            // Act
            var result = controller.Delete(2);

            // Assert
            Assert.That(controller.TempData["ErrorMessage"], Is.EqualTo("Cannot Find incident"));
            result.ShouldBeRedirectionTo(new { action = "List", page = 1 });
        }

    }
}
